package com.chatplus.application.controller.admin.biz;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chatplus.application.common.logging.SouthernQuietLogger;
import com.chatplus.application.common.logging.SouthernQuietLoggerFactory;
import com.chatplus.application.domain.entity.account.UserEntity;
import com.chatplus.application.domain.entity.chat.ChatHistoryEntity;
import com.chatplus.application.domain.entity.chat.ChatItemEntity;
import com.chatplus.application.domain.entity.orders.OrderEntity;
import com.chatplus.application.domain.response.admin.DashboardStatsResponse;
import com.chatplus.application.enumeration.OrderStatusEnum;
import com.chatplus.application.service.account.UserService;
import com.chatplus.application.service.chat.ChatHistoryService;
import com.chatplus.application.service.chat.ChatItemService;
import com.chatplus.application.service.orders.OrderService;
import com.chatplus.application.web.basecontroller.BaseController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 图标指标
 */
@Validated
@RestController
@RequestMapping("/api/admin/dashboard")
@Tag(name = "首页统计API", description = "首页统计API")
public class DashboardAdminApiController extends BaseController {
    static final SouthernQuietLogger LOGGER = SouthernQuietLoggerFactory.getLogger(DashboardAdminApiController.class);
    private final UserService usersService;
    private final ChatItemService chatItemService;
    private final ChatHistoryService chatHistoryService;
    private final OrderService orderService;

    public DashboardAdminApiController(UserService usersService, ChatItemService chatItemService, ChatHistoryService chatHistoryService, OrderService orderService) {
        this.usersService = usersService;
        this.chatItemService = chatItemService;
        this.chatHistoryService = chatHistoryService;
        this.orderService = orderService;
    }

    /**
     * 图标指标
     */
    @GetMapping("/stats")
    @Operation(summary = "图表指标")
    public DashboardStatsResponse stats() {
        try {
            // 获取今日新增用户数
            long users = usersService.count(Wrappers.<UserEntity>lambdaQuery()
                    .ge(UserEntity::getCreatedAt, DateUtil.beginOfDay(DateUtil.date()).toInstant())
                    .le(UserEntity::getCreatedAt, DateUtil.endOfDay(DateUtil.date()).toInstant())
                    .ne(UserEntity::getAdmin, false)
            );
            // 统计今日新增对话数
            long chats = chatItemService.count(Wrappers.<ChatItemEntity>lambdaQuery()
                    .ge(ChatItemEntity::getCreatedAt, DateUtil.beginOfDay(DateUtil.date()).toInstant())
                    .le(ChatItemEntity::getCreatedAt, DateUtil.endOfDay(DateUtil.date()).toInstant())
            );
            // 统计tokens
            long tokens = chatHistoryService.list(Wrappers.<ChatHistoryEntity>lambdaQuery()
                    .ge(ChatHistoryEntity::getCreatedAt, DateUtil.beginOfDay(DateUtil.date()).toInstant())
                    .le(ChatHistoryEntity::getCreatedAt, DateUtil.endOfDay(DateUtil.date()).toInstant())
            ).stream().mapToLong(ChatHistoryEntity::getTokens).sum();
            // 统计今日订单总金额
            BigDecimal income = orderService.list(Wrappers.<OrderEntity>lambdaQuery()
                    .ge(OrderEntity::getCreatedAt, DateUtil.beginOfDay(DateUtil.date()).toInstant())
                    .le(OrderEntity::getCreatedAt, DateUtil.endOfDay(DateUtil.date()).toInstant())
                    .eq(OrderEntity::getStatus, OrderStatusEnum.SUCCESS)
            ).stream().map(OrderEntity::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

            DashboardStatsResponse response = new DashboardStatsResponse(users, chats, tokens, income);
            DashboardStatsResponse.ChartDto chart = new DashboardStatsResponse.ChartDto();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
                    .withZone(ZoneId.systemDefault());

            Instant start = DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -7)).toInstant();
            Instant end = DateUtil.endOfDay(DateUtil.date()).toInstant();
            // 获取开始到结束每一天格式为yyyy-MM-dd的日期List
            List<String> dateList = DateUtil.rangeToList(DateUtil.date(start), DateUtil.date(end), DateField.DAY_OF_YEAR).stream()
                    .map(date -> DateUtil.format(date, "yyyy-MM-dd"))
                    .toList();
            // 最近7日每日用户注册数 users
            Map<String, Integer> userMap = usersService.list(Wrappers.<UserEntity>lambdaQuery()
                    .between(UserEntity::getCreatedAt, start, end)
                    .ne(UserEntity::getAdmin, false)
            ).stream().collect(HashMap::new, (m, u) -> m.put(formatter.format(u.getCreatedAt()), 1), HashMap::putAll);
            // 最近7日每日收入收入 orders
            Map<String, Integer> orders = orderService.list(Wrappers.<OrderEntity>lambdaQuery()
                    .between(OrderEntity::getCreatedAt, start, end)
                    .eq(OrderEntity::getStatus, OrderStatusEnum.SUCCESS)
            ).stream().collect(HashMap::new, (m, o) -> m.put(formatter.format(o.getCreatedAt()), o.getAmount().intValue()), HashMap::putAll);
            // 最近7日每日Token消耗 historyMessage,如果没有数据，这个日期则设置为0
            Map<String, Integer> historyMessage = chatHistoryService.list(Wrappers.<ChatHistoryEntity>lambdaQuery()
                    .between(ChatHistoryEntity::getCreatedAt, start, end)
            ).stream().collect(HashMap::new, (m, h) -> m.put(formatter.format(h.getCreatedAt()), h.getTokens().intValue()), HashMap::putAll);

            dateList.forEach(date -> {
                userMap.putIfAbsent(date, 0);
                orders.putIfAbsent(date, 0);
                historyMessage.putIfAbsent(date, 0);
            });
            chart.setOrders(orders);
            chart.setUsers(userMap);
            chart.setHistoryMessage(historyMessage);
            response.setChart(chart);
            return response;
        } catch (Exception e) {
            LOGGER.message("图标指标调用失败")
                    .exception(e).error();
        }
        return new DashboardStatsResponse(0, 0, 0, BigDecimal.ZERO);
    }

}
